#include <cstring>
#include <dirent.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;

char **readSourceFileName(const char *path); //读取源文件名称
int readFilenum(const char *path); //读取文件夹内.cpp/.h源文件数量

char **readBasename(const char* astpath); //读AST.txt文件中的基类名称并存入数组
char **readChildname(const char* astpath); //读AST.txt文件中的子类名称并存入数组

int AST(const char *ASTOut);
int traverseAST(const char *AST);

int main(int argc, char *argv[]) {
  int i;
  char *filepath = argv[1];
  const char *filepath2 = "~/Desktop/graph/";
  const char *astpath = "/home/song/Desktop/graph/AST.txt";
  int j;
/*  char **filename = readSourceFileName(filepath);
  int filenum = readFilenum(filepath);
  for (j = 0; j < filenum; j++) {
    cout << "filename: " << filename[j] << endl;
  }
*/

char **base=readBasename(astpath);
  for(i=0;i<20;i++)
{
 if(strlen(base[i])==0)  //通过strlen(classname[i]==0)来判断字符数组什么时候结束
    break;
 cout<<base[i]<<endl;
}
  cout<<"child[]: "<<endl;
char **child=readChildname(astpath);
  for(i=0;i<20;i++)
{
 if(strlen(child[i])==0)  //通过strlen(classname[i]==0)来判断字符数组什么时候结束
    break;
 cout<<child[i]<<endl;
}


  return 0;
}

char **readSourceFileName(const char *path) //读取源文件名称
{
  char *newpath = new char[50];
  strcpy(newpath, path);
  char **namelist;
  DIR *dp;
  struct dirent *dirp;
  int n = 0, i, j, flagname = 0;
  namelist = (char **)malloc(20 * sizeof(char *));
  for (i = 0; i < 20; i++)
    namelist[i] = (char *)malloc(256 * sizeof(char));

  if ((dp = opendir(path)) == NULL) {
    cout << "can't open files" << endl;
  }

  while (((dirp = readdir(dp)) != NULL) && (n <= 50)) {
    int i, j;

    if (memcmp(".", dirp->d_name, 1) == 0) //忽略.和..文件夹
    {
    } else {
      for (i = 0, j = strlen(dirp->d_name) - 1; i < j; i++, j--) { //文件名逆序
        char c = dirp->d_name[i];
        dirp->d_name[i] = dirp->d_name[j];
        dirp->d_name[j] = c;
      }
      if ((memcmp(dirp->d_name, "p", 1) == 0) ||
          (memcmp(dirp->d_name, "h", 1) == 0)) //文件名结尾是p/h，保存下来
      {
        for (i = 0, j = strlen(dirp->d_name) - 1; i < j;
             i++, j--) { //文件名逆序
          char c = dirp->d_name[i];
          dirp->d_name[i] = dirp->d_name[j];
          dirp->d_name[j] = c;
        }
        memcpy(namelist[flagname], dirp->d_name,
               20); //将.cpp文件名保存到namelist[]
        strcat(newpath, namelist[flagname]);
        strcpy(namelist[flagname], newpath);
        strcpy(newpath, path);
        flagname++;
      }
    }
    n++;
  }
  closedir(dp);
  return namelist;
}

int readFilenum(const char *path) //读取文件夹内.cpp源文件数量
{
  DIR *dp;
  struct dirent *dirp;
  int n = 0, i, j;
  if ((dp = opendir(path)) == NULL)
    return -1; //-1表示未正常打开文件夹

  while (((dirp = readdir(dp)) != NULL) && (n <= 50)) {
    if (memcmp(".", dirp->d_name, 1) == 0) {
    } else {
      for (i = 0, j = strlen(dirp->d_name) - 1; i < j; i++, j--) { //文件名逆序
        char c = dirp->d_name[i];
        dirp->d_name[i] = dirp->d_name[j];
        dirp->d_name[j] = c;
      }
      if ((memcmp(dirp->d_name, "p", 1) == 0) ||
          (memcmp(dirp->d_name, "h", 1) == 0)) //结尾是p/h的要计数，xxx.cpp
      {
        n++;
      }
    }
  }

  closedir(dp);
  return n;
}

int AST(const char *ASTOut) {

  ofstream outFile;
  if (!outFile) {
    cout << "no file" << endl;
    return -1;
  } else {
    outFile.open("AST.txt", ios::app); // 打开模式可省略
  }
  outFile << ASTOut << ":" << endl;
  outFile << ASTOut << endl;

  outFile.close();

  return 0;
}

int traverseAST(const char *AST) {
  cout << "AST: " << AST << endl;

  id_t pid = fork(); //子进程
  if (pid == -1) { // pid=-1时，无法开启子进程，输出出错原因，返回-1
    // system error
    cout << "system error" << endl;
    return -1;
  } else if (
      pid !=
      0) { // parent   pid=0
           // 是父进程，需要等待子进程执行完毕再执行父进程，并返回子进程的执行状态status
    int status;
    waitpid(pid, &status, 0);
    return status;
  } else { // pid不为-1、不为0时，是子进程
    execl("/home/song/Desktop/llvm2/AST/build/AST",
          "/home/song/Desktop/llvm2/AST/build/AST",
          "/home/song/Desktop/llvm2/AST/build/father.hpp", nullptr);
  }
}


char **readBasename(const char* astpath)
{
 //   const char *astold = "/home/song/Desktop/graph/AST.txt";
  int i;
  std::ifstream fin(astpath);
  std::string line;
  char **classname;
  classname=(char **)malloc(20*sizeof(char *));
	for (i=0;i<20;i++)
		classname[i]=(char *)malloc(256*sizeof(char));
   int n=0;
  while (getline(fin, line)) {
    const char *cstr = line.c_str();
    char *pc = new char[100];
    strcpy(pc, cstr);
    int i;
    if (pc[0] == '4'&& pc[1]=='4') {
          int j;
          for(i=9;pc[i]!=',';i++)
          {
              classname[n][i-9]=pc[i];  //将“,”后边的类名称存入字符数组
          }
         n++;
        }
  }
cout<<classname[4]<<"base[]: "<<endl;

 fin.close();
  return classname;

}


char **readChildname(const char* astpath)
{
 //   const char *astold = "/home/song/Desktop/graph/AST.txt";
  int i;
  std::ifstream fin(astpath);
  std::string line;
  char **classname;
  classname=(char **)malloc(20*sizeof(char *));
	for (i=0;i<20;i++)
		classname[i]=(char *)malloc(256*sizeof(char));
   int n=0;
   int flag=0;
  while (getline(fin, line)) {
    const char *cstr = line.c_str();
    char *pc = new char[100];
    strcpy(pc, cstr);
    int i;
    if (pc[0] == '4'&& pc[1]=='4') {
          int j;
          for(i=strlen(pc)-1;pc[i]!=',';i--)
          {
                flag++;
          }
          for(i=0;i<flag;i++)
         {
               classname[n][i]=pc[strlen(pc)-flag+i];  //将second“,”后边的类名称存入字符数组
          }
         n++;
         flag=0;
        }
  }

 fin.close();
  return classname;

}
